<template>
  <div class="qrcode-scanner">
    <!-- 摄像头视频容器 -->
    <div v-if="hasCamera" class="camera-container">
      <video 
        ref="video" 
        class="video-element" 
        autoplay 
        muted 
        playsinline
      ></video>
      <!-- 二维码识别框 -->
      <div class="scan-frame"></div>
    </div>
    
    <!-- 加载状态 -->
    <div v-else class="loading">
      <text>正在请求摄像头权限...</text>
    </div>
    
    <!-- 识别结果 -->
    <div v-if="scanResult" class="result-container">
      <text class="result-text">{{ scanResult }}</text>
      <button @click="restartScan">重新扫描</button>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, onBeforeUnmount } from 'vue';
import jsQR from 'jsqr'; // 需先安装：npm install jsqr

// 组件状态
const video = ref(null);
const hasCamera = ref(false);
const scanResult = ref(null);
const scannerActive = ref(true);
const scanInterval = ref(null);

// 摄像头初始化
const initCamera = async () => {
  try {
    // 申请摄像头权限（非HTTPS环境下部分浏览器可能拒绝）
    const stream = await navigator.mediaDevices.getUserMedia({
      video: { facingMode: 'environment' } // 后置摄像头，'user'为前置 environment
    });
    
    if (video.value) {
      video.value.srcObject = stream;
      video.value.play();
      hasCamera.value = true;
      
      // 启动二维码扫描循环
      startScan();
    }
    
    // 组件销毁时释放资源
    onBeforeUnmount(() => {
      if (stream) {
        stream.getTracks().forEach(track => track.stop());
      }
      stopScan();
    });
  } catch (error) {
    console.error('摄像头权限申请失败:', error);
    hasCamera.value = false;
  }
};

// 启动扫描循环
const startScan = () => {
  if (scanInterval.value) return;
  
  scanInterval.value = setInterval(() => {
    if (!scannerActive.value || !video.value || !video.value.readyState) return;
    
    try {
      // 创建画布用于图像捕获
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      
      // 设置画布尺寸与视频一致
      canvas.width = video.value.videoWidth;
      canvas.height = video.value.videoHeight;
      
      // 将视频帧绘制到画布上
      ctx.drawImage(video.value, 0, 0, canvas.width, canvas.height);
      
      // 获取画布像素数据
      const imageData = ctx.getImageData(
        0, 
        0, 
        canvas.width, 
        canvas.height
      );
      
      // 使用jsQR识别二维码
      const code = jsQR(
        imageData.data,
        imageData.width,
        imageData.height,
        {
          inversionAttempts: 'dontInvert' // 可根据场景调整反转尝试
        }
      );
      
      // 处理识别结果
      if (code && code.data && scanResult.value !== code.data) {
        scanResult.value = code.data;
        stopScan(); // 识别成功后停止扫描
      }
    } catch (error) {
      console.log('扫描过程中出错:', error);
    }
  }, 300); // 每300ms扫描一次，可调整频率
};

// 停止扫描
const stopScan = () => {
  if (scanInterval.value) {
    clearInterval(scanInterval.value);
    scanInterval.value = null;
  }
  scannerActive.value = false;
};

// 重新扫描
const restartScan = () => {
  scanResult.value = null;
  scannerActive.value = true;
  startScan();
};

// 组件挂载时初始化
onMounted(() => {
  initCamera();
});

// 组件卸载时清理资源
onUnmounted(() => {
  stopScan();
});
</script>

<style scoped>
.qrcode-scanner {
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: #000;
}

.camera-container {
  position: relative;
  width: 90%;
  max-width: 600px;
  height: auto;
}

.video-element {
  width: 100%;
  border-radius: 10px;
}

.scan-frame {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 240px;
  height: 240px;
  border: 2px solid #42b983;
  border-radius: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.scan-frame::before,
.scan-frame::after {
  content: '';
  position: absolute;
  width: 100%;
  height: 2px;
  background-color: #42b983;
}

.scan-frame::before {
  top: 0;
}

.scan-frame::after {
  bottom: 0;
}

.scan-frame::before,
.scan-frame::after,
.scan-frame::before::before,
.scan-frame::before::after {
  animation: scan 2s linear infinite;
}

@keyframes scan {
  0% {
    transform: scaleX(0);
  }
  50% {
    transform: scaleX(1);
  }
  100% {
    transform: scaleX(0);
  }
}

.loading, .result-container {
  margin-top: 20px;
  color: #fff;
  text-align: center;
}

.result-text {
  display: block;
  margin-bottom: 10px;
  padding: 10px;
  background-color: rgba(255, 255, 255, 0.2);
  border-radius: 5px;
  max-width: 80%;
}
</style>